package absolute_zero.com.urbox;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Contacts;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class ContactSearch extends Activity 
{
	private ListView resultList;
	private EditText searchTerm;
	//private ArrayList<String> results;
	private boolean isPhoneNumber = true;
	private Filter dataFilter;
	//private String selectedContact = "";
	private ArrayList<Contact> contacts;
	private Map<String, String>	contactsWithEmails;
	private Map<String, byte[]> contactsWithPhotos;
	private ContactAdapter adapter;
	private String filepath;
	
	/** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) 
  {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.contact_search);
      
      //fetch the filepath
      
      Bundle UserInfo = getIntent().getExtras();
		filepath = (String)UserInfo.get("Filepath");
      	//filepath = "/sdcard/urbox/evilhardcodedvalue";
      contacts = new ArrayList<Contact>();
      
      Cursor phoneCursor = getContentResolver().query(Contacts.Phones.CONTENT_URI, null, null, null, null); //for whatever reason, i can't get all the data from one cursor
      startManagingCursor(phoneCursor);
      
      Cursor emailCursor = getContentResolver().query(Contacts.ContactMethods.CONTENT_URI, null, null, null, null); 
      startManagingCursor(emailCursor); 
      
      Cursor photoCursor = getContentResolver().query(Contacts.Photos.CONTENT_URI, null, null, null, null);
      startManagingCursor(photoCursor);
      
      int phoneIndex = phoneCursor.getColumnIndex(Contacts.PhonesColumns.NUMBER);
      int phoneTypeIndex = phoneCursor.getColumnIndex(Contacts.PhonesColumns.TYPE);
      int nameIndex = phoneCursor.getColumnIndex(Contacts.PeopleColumns.NAME);
      int personID = phoneCursor.getColumnIndex(Contacts.Phones.PERSON_ID);
      
      int emailIndex = emailCursor.getColumnIndex(Contacts.ContactMethods.DATA);
      int dataType = emailCursor.getColumnIndex(Contacts.ContactMethods.KIND);
      int emailPersonID = emailCursor.getColumnIndex(Contacts.ContactMethods.PERSON_ID);
      
      int photoIndex = photoCursor.getColumnIndex(Contacts.PhotosColumns.DATA);
      int photoPersonID = photoCursor.getColumnIndex(Contacts.PhotosColumns.PERSON_ID);
      
      if (photoCursor.getCount() > 0)
      {
	      contactsWithPhotos = new TreeMap<String, byte[]>();  
	      photoCursor.moveToFirst();
	      do
	      {
	    	  contactsWithPhotos.put(photoCursor.getString(photoPersonID), photoCursor.getBlob(photoIndex)); // map pictures to personIDs
	      }
	      while (photoCursor.moveToNext());
      }
      photoCursor.close();
      
      if (emailCursor.getCount() > 0)
      {
	      contactsWithEmails = new TreeMap<String, String>();
	      emailCursor.moveToFirst();
	      do
	      {
	    	  if (emailCursor.getString(dataType).equals(Integer.toString(Contacts.KIND_EMAIL))) //if it is an email address in the data field
	    		  contactsWithEmails.put(emailCursor.getString(emailPersonID), emailCursor.getString(emailIndex)); //map emails to personIDs
	      }
	      while (emailCursor.moveToNext());
      }
      emailCursor.close();
      
      if (phoneCursor.getCount() > 0)
      {
	      phoneCursor.moveToFirst();
	      do
	      {
	    	  if (phoneCursor.getString(phoneIndex) != null && phoneCursor.getString(phoneTypeIndex).equals(Integer.toString(Contacts.PhonesColumns.TYPE_MOBILE))) //if the contact has a mobile phone number
	    	  {//combine this data with the data in the two trees and create a contact from the data
 	    		try{
	    	  		  contacts.add(new Contact(phoneCursor.getString(nameIndex), phoneCursor.getString(phoneIndex), contactsWithEmails.get(phoneCursor.getString(personID)), contactsWithPhotos.get(phoneCursor.getString(personID))));  
	    		}catch(NullPointerException e){
	    			Log.d("NULL POINTER ERROR!!!", "hello" /* + e.getMessage()*/);
	    		}
}
	      }
	      while (phoneCursor.moveToNext());
      }
      phoneCursor.close();
      
      Collections.sort(contacts); //sort by name
      
      adapter = new ContactAdapter(contacts); //set up the list
      resultList = (ListView)this.findViewById(R.id.SearchResults);
      resultList.setAdapter(adapter);
      
      resultList.setOnItemClickListener(new OnItemClickListener()
      {
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
			{
				//Log.d("Selected Position: ", Integer.toString(position));
				//selectedContact = resultList.getItemAtPosition(position).toString();
				//Log.d("Selected Contact:", selectedContact);
				Contact selected = (Contact)resultList.getItemAtPosition(position);
				String number = selected.getNumber();
				String name = selected.getName();
				//be sure to sanitze input aka. deleted "-" from number
				number = getOnlyNumerics(number);
				Log.d("Number Sent to", number);
				//Write pertinant info to a file
				Log.d("ContactSearch Filepatch for Transmission", filepath);
				WriteToFile(filepath, number);
				//Fire SMS sending sequence
				Intent next_intent = new Intent(ContactSearch.this, File_transmission.class);
            		Bundle destination_information = new Bundle();
            		destination_information.putString("destination", number);
            		destination_information.putString("name", name);
            		destination_information.putString("filepath", filepath);
            		next_intent.putExtras(destination_information);	
				  	startActivityForResult(next_intent, 0x37);
			}
      });
      dataFilter = adapter.getFilter(); //set up the filter
      searchTerm = (EditText)this.findViewById(R.id.SearchTerm);
      searchTerm.setOnKeyListener(new OnKeyListener()
      {
      	public boolean onKey(View v, int keyCode, KeyEvent event)
      	{
      		formatInput(keyCode); //makes phone numbers pretty
      		return false;
      	}
		});
  }
  
  @Override
  protected void onActivityResult( int requestCode, int resultCode,
  Intent data ){
	 finish();
  }
  
  public static String getOnlyNumerics(String str) {
	    
	    if (str == null) {
	        return null;
	    }

	    StringBuffer strBuff = new StringBuffer();
	    char c;
	    
	    for (int i = 0; i < str.length() ; i++) {
	        c = str.charAt(i);
	        
	        if (Character.isDigit(c)) {
	            strBuff.append(c);
	        }
	    }
	    return strBuff.toString();
	}
private void WriteToFile(String filepath, String number) {
		try{
			File root = Environment.getExternalStorageDirectory();
			if(root.canWrite()){
				Log.d("Writing to:", root.toString() + filepath);
				File dir = new File(root + "/urbox/tmp");
				File datafile = new File(dir, number + ".ubx");
				FileWriter datawriter = new FileWriter(datafile);
				BufferedWriter out = new BufferedWriter(datawriter);
				out.write(filepath);
				out.close();
			}
		}catch(IOException e){
			Log.e("Whoops", "Can't write" + e.getMessage());
		}
		
	}
	
  private void formatInput(int keyCode) //makes phone numbers match the format they are stored in android database
  {
  	String input = searchTerm.getText().toString();
  	String[] phoneNumberCheck = input.split("-");
  	
  	if (keyCode != KeyEvent.KEYCODE_DPAD_DOWN && keyCode != KeyEvent.KEYCODE_DPAD_UP && keyCode != KeyEvent.KEYCODE_DPAD_LEFT && keyCode != KeyEvent.KEYCODE_DPAD_RIGHT)
  	{
  		if (isPhoneNumber || keyCode == KeyEvent.KEYCODE_DEL)
  		{
	    		for (String column: phoneNumberCheck)
	    		{
	    			if (column != "")
	    			{
		    			try 
			    		{
			    			Integer.parseInt(column);
			    			isPhoneNumber = true;
			    		}
			    		catch (NumberFormatException e)
			    		{
			    			Log.d("Error:", column + " is not a phone number. Assuming name or email entry instead.");
			    			isPhoneNumber = false;
			    		}
	    			}
		    	}
  		}
	    	if (isPhoneNumber && keyCode != KeyEvent.KEYCODE_DEL)
	    	{
	    		if (input.length() == 1 && input.equals("1"))
	    			input = input + "-";
	    		else if (input.contains("-"))
	    		{
	    			if (input.indexOf("-") == 1)
	    			{
	    				if (input.length() == 5)
	    					input = input + "-";
	    				else if (input.length() == 9)
	    					input = input + "-";
	    			}
	    			else if (input.indexOf("-") == 3)
	    			{
	    				if (input.length() == 9)
	    					input = input.substring(0,7) + "-" + input.substring(7,9);
	    			}
	    		}
	    		else if (!input.contains("-") && input.length() == 3)
	    			input = input + "-";
	    	}
	    	searchTerm.setText(input); //update text box
	    	searchTerm.setSelection(input.length()); //move the cursor to the end again, otherwise they start typing at the beginning
	    	dataFilter.filter(input); //actually filter the data
  	}
  }
  
  private boolean checkInput() //makes sure the contents of the EditText is a phone number
  {
	  boolean response = true;
	  String input = searchTerm.getText().toString();
	  for (int i = 0; i < input.length(); i++)
	  {
		  if (!input.substring(i, i+1).equals("0") && !input.substring(i, i+1).equals("1") && !input.substring(i, i+1).equals("2") && !input.substring(i, i+1).equals("3") && !input.substring(i, i+1).equals("4") && !input.substring(i, i+1).equals("5") && !input.substring(i, i+1).equals("6") && !input.substring(i, i+1).equals("7") && !input.substring(i, i+1).equals("8") && !input.substring(i, i+1).equals("9") && !input.substring(i, i+1).equals("-"))
			  response = false;
	  }
	  Log.d("Input check results:", Boolean.toString(response));
	  return response;
  }
 
  private class ContactAdapter extends BaseAdapter implements ListAdapter
  {
	  private ContactFilter filter;
      private Context context;
      private final ArrayList<Contact> allContacts;
      private ArrayList<Contact> filteredContacts;
      

      public ContactAdapter(ArrayList<Contact> data)
      {
              context = ContactSearch.this;
              allContacts = data;
              filteredContacts = allContacts;
      }
      public View getView(int position, View convertView, ViewGroup parent) 
      {
    	  LinearLayout layout = new LinearLayout(context);
       	  ImageView picture = new ImageView(context);
          	  
       	  Bitmap image = filteredContacts.get(position).getPicture();
       	  if (image == null)
       	  {
         		  picture.setImageDrawable(getResources().getDrawable(R.drawable.contact));
       	  }
       	  else
     		  picture.setImageBitmap(image);
			           	  
       	  layout.setOrientation(LinearLayout.HORIZONTAL);
	   	  picture.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT));
	   	  layout.addView(picture);
			           	  
	   	  TextView information = new TextView(context);
	  	  information.setText(" " + filteredContacts.get(position).getName() + " \n     " + filteredContacts.get(position).getNumber() + " \n     " + filteredContacts.get(position).getEmail());
	   	  information.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT));
	   	  layout.addView(information);
	   	  return(layout);
      }
      public Filter getFilter()
      {
    	  if (filter == null)
    		  filter = new ContactFilter();
    	  return filter;
      }

      public int getCount()
      {
    	  return filteredContacts.size();
      }
      public Object getItem(int position)
      {
    	  return filteredContacts.get(position);
      }
      public long getItemId(int position) //i'm not really sure what this should be...
      {
    	  return 00000; //so i'll just throw out this for now, hopefully you don't actually need it
      }

  
  private class ContactFilter extends Filter
  {
	  @SuppressWarnings("unchecked")
	  @Override
	  protected FilterResults performFiltering(CharSequence term)
	  {
		  FilterResults results = new FilterResults();
		  String searchTerm = term.toString().toLowerCase();
		  
		  filteredContacts = (ArrayList<Contact>)allContacts.clone();
		  Log.d("Filter:", searchTerm);
		  if (searchTerm != null && searchTerm.length() > 0)
		  {
			  for (int index = filteredContacts.size() - 1; index >= 0; index --)
			  {
				  Contact temp = filteredContacts.get(index);
				  //Log.d("Temp Contact", temp.toString());
				  if (!temp.getName().toLowerCase().contains(searchTerm) && !temp.getNumber().toLowerCase().contains(searchTerm) && !temp.getEmail().toLowerCase().contains(searchTerm))
					  filteredContacts.remove(index);
			  }
			  results.values = filteredContacts;
			  results.count = filteredContacts.size();
		  }
		  else
		  {
			  results.values = allContacts;
			  results.count = allContacts.size();
		  }
		  Log.d("Filter Results size:", Integer.toString(results.count));
		  //Log.d("Filter Results", results.values.toString());
		  return results;
		}
	  
	  @SuppressWarnings("unchecked")
	  @Override
	  protected void publishResults(CharSequence prefix, FilterResults results)
	  {
		  if (results.count > 0)
		  {
			  filteredContacts = (ArrayList<Contact>) results.values;
			  Collections.sort(filteredContacts); //sort by name
		  }
		  else if (checkInput())
		  {
			  ArrayList<Contact> temp = new ArrayList<Contact>();
			  Contact newContact = new Contact("Unknown Contact", searchTerm.getText().toString(), null, null);
			  temp.add(newContact);
			  filteredContacts = temp;
		  }
		  notifyDataSetChanged();
	  }
	}
  }
  private class Contact implements Comparable<Contact>
  {
	  private String name, number, email;
	  private Bitmap picture;
	  
	  public Contact()
	  {
		  name = "";
		  number = "";
		  email = "";
		  picture = null;
	  }
	  public Contact(String newName, String newNumber, String newEmail, byte[] newPicture)
	  {
		  name = newName;
		  number = newNumber;
		  if (newEmail == null)
			  email = "";
		 else
			  email = newEmail;
		  if (newPicture == null)
			  picture = null;
		  else
			  picture = BitmapFactory.decodeByteArray(newPicture, 0, newPicture.length);
	  }
	  public String getName()
	  {
		  return name;
	  }
	  public String getNumber()
	  {
		  return number;
	  }
	  public String getEmail()
	  {
		  return email;
	  }
	  public Bitmap getPicture()
	  {
		  return picture;
	  }
	  public void setName(String newName)
	  {
		  name = newName;
	  }
	  public void setNumber(String newNumber)
	  {
		  number = newNumber;
	  }
	  public void setEmail(String newEmail)
	  {
		  email = newEmail;
	  }
	  public void setPicture(byte[] newPicture)
	  {
		  picture = BitmapFactory.decodeByteArray(newPicture, 0, newPicture.length);
	  }
	  public String toString()
	  {
		  return name + " \n     " + number + " \n     " + email;
	  }
	  public int compareTo(Contact other) //we sort by name here, i don't know why you would sort by anything else
	  {
		  return name.compareTo(other.getName());
	  }
	  public boolean equals(Contact other)
	  {
		  return name == other.getName() && number == other.getNumber() && email == other.getEmail() && picture == other.getPicture();
	  }
  }
}